package cn.sciento.websocket.listener;

import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;

import org.apache.commons.collections4.CollectionUtils;
import cn.sciento.websocket.redis.BrokerSessionRedis;
import cn.sciento.websocket.registry.SessionRegistry;
import cn.sciento.websocket.vo.MsgVO;
import cn.sciento.websocket.vo.UserVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;

@Component
public class RedisListener {
    private static final Logger logger = LoggerFactory.getLogger(RedisListener.class);

    @Autowired
    private ObjectMapper objectMapper;

    public void messageListener(String msgVO) {
        try {
            WebSocketSession session;
            List<UserVO> userList;
            List<String> sessionIdList;
            List<UserVO> users;
            List<String> sessionIds;
            MsgVO msg = this.objectMapper.readValue(msgVO, MsgVO.class);
            Long userId = msg.getUserId();
            String brokerId = SessionRegistry.getBrokerId();
            switch (msg.getType()) {
                case "S":
                    session = SessionRegistry.getSession(msg.getSessionId());
                    if (session.isOpen()) {
                        try {
                            session.sendMessage(new TextMessage(msgVO));
                        } catch (IOException e) {
                            logger.warn("send webSocket message failed , message : {}", msgVO);
                        }
                    }
                    break;
                case "U":
                    userList = BrokerSessionRedis.getCache(brokerId, userId);
                    sessionIdList = userList.stream().map(UserVO::getSessionId).collect(Collectors.toList());
                    send(sessionIdList, msgVO);
                    break;
                case "A":
                    users = BrokerSessionRedis.getCache(brokerId);
                    sessionIds = users.stream().map(UserVO::getSessionId).collect(Collectors.toList());
                    send(sessionIds, msgVO);
                    break;
            }
        } catch (IOException e) {
            logger.warn(e.getMessage());
        }
    }

    private void send(List<String> sessionIds, String msgVO) {
        List<WebSocketSession> sessions = SessionRegistry.getSession(sessionIds);
        if (CollectionUtils.isNotEmpty(sessions)) {
            for (WebSocketSession session : sessions) {
                if (session != null && session.isOpen()) {
                    try {
                        session.sendMessage(new TextMessage(msgVO));
                    } catch (IOException e) {
                        logger.debug("send webSocket message failed , message : {}", msgVO);
                    }
                }
            }
        }
    }
}
